package redis

import (
	"context"
	"github.com/go-redis/redis/v8"
	"log"
	"strings"
)

// RedisV8
//---------------------------------
//	创建 redis-v8 版本结构体
// ---------------------------------
type RedisV8 struct {
	Client redis.Cmdable
	Conf   RedisConfig
}

var DefaultRedisV8 *RedisV8

// NewRedisV8
//----------------------------------
//	初始化 redis v8 版本
// ----------------------------------
func NewRedisV8(myHook redis.Hook, redisConfig RedisConfig) error {
	initClient, err := initRedisV8(myHook, redisConfig)

	if err != nil {
		return err
	}
	DefaultRedisV8 = &RedisV8{Client: initClient, Conf: redisConfig}
	return nil
}

func initRedisV8(myHook redis.Hook, redisConfig RedisConfig) (redis.Cmdable, error) {

	if strings.Contains(redisConfig.GetAddr(), ",") {
		return initRedisClusterV8(myHook, redisConfig)
	} else {
		return initRedisNormalV8(myHook, redisConfig)
	}
}

// ------------------------------------
//	集群版本 redis 配置
// ------------------------------------
func initRedisClusterV8(myHook redis.Hook, redisConfig RedisConfig) (redis.Cmdable, error) {
	if len(redisConfig.GetAddr()) == 0 {
		log.Fatal("null redis addr")
	}
	addrSegs := strings.Split(redisConfig.GetAddr(), ",")
	client := redis.NewClusterClient(&redis.ClusterOptions{
		Addrs:          addrSegs,
		PoolSize:       redisConfig.GetPoolNum(),
		ReadTimeout:    redisConfig.GetReadTimeout(),
		WriteTimeout:   redisConfig.GetWriteTimeout(),
		PoolTimeout:    redisConfig.GetPoolTimeout(),
		DialTimeout:    redisConfig.GetDialTimeout(),
		Password:       redisConfig.GetPassword(),
		ReadOnly:       redisConfig.GetReadOnly(),
		RouteByLatency: redisConfig.GetRouteByLatency(),
		RouteRandomly:  redisConfig.GetRouteRandomly(),
	})
	_, err := client.Ping(context.Background()).Result()
	if myHook != nil {
		client.AddHook(myHook)
	}
	return client, err
}

// -------------------------------
//		普通redis配置
// -------------------------------
func initRedisNormalV8(myHook redis.Hook, redisConfig RedisConfig) (redis.Cmdable, error) {
	client := redis.NewClient(&redis.Options{
		Addr:         redisConfig.GetAddr(),
		PoolSize:     redisConfig.GetPoolNum(),
		ReadTimeout:  redisConfig.GetReadTimeout(),
		WriteTimeout: redisConfig.GetWriteTimeout(),
		PoolTimeout:  redisConfig.GetPoolTimeout(),
		DialTimeout:  redisConfig.GetDialTimeout(),
		Password:     redisConfig.GetPassword(),
		DB:           redisConfig.GetDb(),
	})
	_, err := client.Ping(context.Background()).Result()
	if err != nil {
		log.Fatalf("init redis ping error:%s", err.Error())
	}
	if myHook != nil {
		client.AddHook(myHook)
	}
	return client, err
}
